package net.oschina.jhssm.common.interceptor;

import net.oschina.jhssm.common.annotation.RequireLog;
import net.oschina.jhssm.common.util.HttpUtil;
import net.oschina.jhssm.common.util.JsonUtil;
import net.oschina.jhssm.common.util.ShiroUtil;
import net.oschina.jhssm.module.system.entity.SysLog;
import net.oschina.jhssm.module.system.entity.SysUser;
import net.oschina.jhssm.module.system.service.ISysLogService;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.NamedThreadLocal;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * Created by zhaojb on 2017/8/21.
 */
public class LogInterceptor extends HandlerInterceptorAdapter {

    private NamedThreadLocal<SysLog> startTimeThreadLocal = new NamedThreadLocal<>("SysLog");

    @Autowired
    private ISysLogService sysLogService;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        if (!(o instanceof HandlerMethod)) {
            return true;
        }
        Method method = ((HandlerMethod) o).getMethod();
        RequireLog requireLog = method.getAnnotation(RequireLog.class);
        if (requireLog == null) {
            return true;
        }
        SysLog sysLog = new SysLog();
        sysLog.setConsumeTime(System.currentTimeMillis());
        startTimeThreadLocal.set(sysLog);

        sysLog.setMethodName(new StringBuilder(method.getDeclaringClass().getName()).append(".").append(method.getName()).toString());
        sysLog.setUserOption(requireLog.value());
        sysLog.setUrl(httpServletRequest.getRequestURI());
        sysLog.setReqMethod(httpServletRequest.getMethod());
        Map<String, String[]> reqParameterMap = httpServletRequest.getParameterMap();
        sysLog.setReqParameter(JsonUtil.toJsonString(reqParameterMap));
        sysLog.setIp(HttpUtil.getIpAddr(httpServletRequest));
        SysUser user = ShiroUtil.getUser();
        if (user != null) {
            sysLog.setUsername(user.getUsername());
            sysLog.setUserId(user.getId());
        }
        sysLog.setUserAgent(httpServletRequest.getHeader("User-Agent"));
        sysLog.setReqTime(new DateTime().toDate());
        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        if (!(o instanceof HandlerMethod)) {
            return;
        }
        Method method = ((HandlerMethod) o).getMethod();
        RequireLog requireLog = method.getAnnotation(RequireLog.class);
        if (requireLog == null) {
            return;
        }
        SysLog sysLog = startTimeThreadLocal.get();
        long endTime = System.currentTimeMillis();
        sysLog.setConsumeTime(endTime - sysLog.getConsumeTime());

        sysLog.setGmtCreate(new DateTime().toDate());
        sysLogService.insertSelective(sysLog);
        startTimeThreadLocal.remove();
    }
}
